﻿using System;
using System.Data;
using System.Drawing;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Text;
using System.Globalization;
using System.Net;
using System.IO;

namespace Gollie.Graph
{
	public enum GraphType
	{
		Line,
		VerticalBar
	}

	public enum GraphAxisLabelsPosition
	{
		Left = 1,
		Top = 2,
		Right = 3,
		Bottom = 4
	}

	public class Graph
	{
		string title;
		GraphType graphType = GraphType.VerticalBar;
		GraphAxisLabels axisLabels = new GraphAxisLabels();
		GraphDataSetCollection dataSets = new GraphDataSetCollection();
		GraphGridLines gridLines = new GraphGridLines();
		Color backGroundColor = Color.White;
		int width = 200;
		int height = 100;

		public Graph()
		{
		}

		public Graph(string title)
		{
			this.title = title;
		}

		public void Save(string path)
		{
			try
			{
				HttpWebRequest request = (HttpWebRequest)WebRequest.Create(this.Url);

				// Set some reasonable limits on resources used by this request
				request.MaximumAutomaticRedirections = 4;
				request.MaximumResponseHeadersLength = 4;
				// Set credentials to use for this request.
				request.Credentials = CredentialCache.DefaultCredentials;
				HttpWebResponse response = (HttpWebResponse)request.GetResponse();

				try
				{
					if (response.StatusCode == HttpStatusCode.OK)
					{
						//assume ContentType = image/png
						string type = response.ContentType.ToLower();

						if (type != "image/png")
							throw new Exception("Unknown content type");


						Stream receiveStream = response.GetResponseStream();

						BinaryReader reader = new BinaryReader(receiveStream);

						byte[] data = reader.ReadBytes((int)response.ContentLength);

						BinaryWriter writer = new BinaryWriter(File.Open(path, FileMode.Create, FileAccess.Write, FileShare.None));

						writer.Write(data);

						writer.Close();
					}
				}
				finally
				{
					response.Close();
				}
			}
			catch (Exception e)
			{
				throw new Exception("Save failed", e);
			}
		}

		public static string StringColor(Color color)
		{
			StringBuilder str = new StringBuilder("", 8);
			str.Append(color.R.ToString("x2"));
			str.Append(color.G.ToString("x2"));
			str.Append(color.B.ToString("x2"));
			str.Append(color.A.ToString("x2"));

			return str.ToString();
		}

		public static string StringDouble(double value)
		{
			CultureInfo ci = new CultureInfo("en-us"); // for decimal point

			return value.ToString("0.0", ci);
		}

		public string Url
		{
			get
			{
				StringBuilder str = new StringBuilder("http://chart.apis.google.com/chart?cht=", 1024);
				switch (this.graphType)
				{
					case GraphType.Line:
						str.Append("lc");
						break;
					case GraphType.VerticalBar:
						str.Append("bvg&chbh=a,0,4");
						break;
				}

				if (string.IsNullOrEmpty(this.title) == false)
				{
					str.Append("&chtt=");
					str.Append(HttpUtility.UrlEncode(this.title));
				}

				str.Append("&chs=");
				str.Append(width.ToString());
				str.Append("x");
				str.Append(height.ToString());

				str.Append("&");
				str.Append(this.axisLabels.Url);

				str.Append("&");
				str.Append(this.gridLines.Url);

				str.Append("&chf=bg,s,");
				str.Append(Graph.StringColor(this.backGroundColor));

				str.Append("&");
				str.Append(this.dataSets.Url);

				return str.ToString();
			}
		}

		public GraphAxisLabels AxisLabels
		{
			get { return this.axisLabels; }
		}

		public GraphDataSetCollection DataSets
		{
			get { return this.dataSets; }
		}

		public GraphGridLines GridLines
		{
			get { return this.gridLines; }
		}

		public GraphType GraphType
		{
			get { return this.graphType; }
			set { this.graphType = value; }
		}

		public Color BackGroundColor
		{
			get { return this.backGroundColor; }
			set { this.backGroundColor = value; }
		}

		public int Width
		{
			get { return this.width; }
			set { this.width = value; }
		}

		public int Height
		{
			get { return this.height; }
			set { this.height = value; }
		}

		/// <summary>
		/// Specify | for multiple lines.
		/// </summary>
		public string Title
		{
			get { return this.title; }
			set { this.title = value; }
		}

		public double LowerBound
		{
			get { return this.dataSets.LowerBound; }
			set { this.dataSets.LowerBound = value; }
		}

		public double UpperBound
		{
			get { return this.dataSets.UpperBound; }
			set { this.dataSets.UpperBound = value; }
		}
	}
}